package com.seres.user.service.user;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.seres.client.mapper.user.SysRoleMenuMapper;
import com.seres.client.mapper.user.SysUserMapper;
import com.seres.client.mapper.user.SysUserRoleMapper;
import com.seres.client.model.user.SysMenu;
import com.seres.client.model.user.SysRole;
import com.seres.client.model.user.SysRoleMenu;
import com.seres.client.model.user.SysUserRole;
import com.seres.enums.OftenEnum;
import com.seres.enums.RedisCacheEnum;
import com.seres.redis.RedisCache;
import com.seres.redis.RedisTableCache;
import com.seres.user.cache.MenuCache;
import com.seres.user.vo.user.MenuVo;
import com.seres.user.vo.user.RoleVo;
import com.seres.util.ValidatorTools;
import com.seres.vo.AuthUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Tan-Bowen
 * @version 1.0
 * @description TODO
 * @date 2021/7/26 18:03
 */
@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Resource
    private SysUserMapper userMapper;

    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysRoleMenuMapper roleMenuMapper;

    @Resource
    private RedisCache redisCache;

    @Resource
    private RedisTableCache redisTableCache;

    @Resource
    private MenuCache menuCache;

    @Override
    public List<Long> userRole(long userId) {
        String key = RedisCacheEnum.USER_ROLE.createKey(userId);
        List<Long> roles = redisCache.getList(key, Long.class);
        if (!roles.isEmpty()) {
            return roles;
        }
        List<SysUserRole> userRoles = userRoleMapper.selectList(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        roles = userRoles.stream()
                .map(SysUserRole::getRoleId)
                .filter(roleId ->
                        ValidatorTools.checkAttribute(SysRole::getState, redisTableCache.get(SysRole.class, roleId), OftenEnum.EnableState.ENABLE.getCode()))
                .collect(Collectors.toList());
        if (ValidatorTools.notEmpty(roles)) {
            redisCache.cacheOneWeek(JSON.toJSONString(roles), key);
        }
        return roles;
    }

    @Override
    public List<Long> roleMenu(long roleId) {
        String key = RedisCacheEnum.ROLE_MENU.createKey(roleId);
        List<Long> menus = redisCache.getList(key, Long.class);
        if (!menus.isEmpty()) {
            return menus;
        }
        List<SysRoleMenu> roleMenus = roleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, roleId));
        menus = roleMenus.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        if (!menus.isEmpty()) {
            redisCache.cacheOneWeek(JSON.toJSONString(menus), key);
        }
        return menus;
    }

    @Override
    public List<Long> userMenus(long userId) {
        HashSet<Long> menusSet = new HashSet<>();
        List<Long> roles = this.userRole(userId);
        roles.forEach(e -> menusSet.addAll(roleMenu(e)));
        return new ArrayList<>(menusSet);
    }


    @Override
    public List<SysMenu> getUserMenu(Long userId) {
        List<Long> userMenu = this.userMenus(userId);
        return menuCache.getMenu(userMenu);
    }

    @Override
    public MenuVo.MenuAndAuth getMenuAndAuth(Long userId) {
        List<Long> userMenu = this.userMenus(userId);
        return menuCache.getMenuAndAuth(userMenu);
    }

    @Override
    public MenuVo.MenuAuthId getMenuAndAuthId() {
        long userId = AuthUserInfo.getUserId();
        List<Long> userMenu = this.userMenus(userId);
        return menuCache.getMenuAuthId(userMenu);
    }

    @Override
    public MenuVo.MenuAuthId getMenuAndAuthId(Long roleId) {
        List<Long> userMenu = this.roleMenu(roleId);
        return menuCache.getMenuAuthId(userMenu);
    }


    @Override
    public RoleVo.PageList getUserRole(Long userId) {
        List<Long> roles = this.userRole(userId);
        if (roles.size() > 0) {
            return BeanUtil.copyProperties(redisTableCache.get(SysRole.class, roles.get(0)), RoleVo.PageList.class);
        }
        return null;
    }

    @Override
    public void bandUserRole(Long userId, Long roleId) {
        userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        if (roleId != null) {
            ValidatorTools.checkSqlSuccess(userRoleMapper.insert(SysUserRole.builder().userId(userId).roleId(roleId).build()), "给用户绑定角色失败");
        }
        redisTableCache.remove(SysUserRole.class, userId);
        redisCache.del(RedisCacheEnum.USER_ROLE.createKey(userId));
    }

}
